package lion.netty4.message;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.protobuf.GeneratedMessageV3;
import com.google.protobuf.MessageLite;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import lion.common.ProcessorStatManager;
import lion.netty4.core.Netty4Server;
import lion.netty4.proto.RpcBaseProto.RetCode;

public class GamePlayer {

	private static Logger logger = LoggerFactory.getLogger(GamePlayer.class);

	private Channel channel;

	private long lastVisitTime;

	public GamePlayer(Channel channel) {
		this.setChannel(channel);
	}

	public void sendMsg(Object obj) {
		if (obj == null || !getChannel().isActive()) {
			return;
		}
		getChannel().write(obj);
	}

	public String getAddress() {
		String addr = "";
		if (getChannel().remoteAddress() != null) {
			addr += getChannel().remoteAddress().toString();
		}
		return addr;
	}

	public ByteBufAllocator alloc() {
		return getChannel().alloc();
	}

	public long getLastVisitTime() {
		return lastVisitTime;
	}

	public void setLastVisitTime(long lastVisitTime) {
		this.lastVisitTime = lastVisitTime;
	}

	public void write(SendToMessage respMsg) {
		if (!channel.isActive()) {
			return;
		}
		getChannel().write(respMsg);
	}
	
	public void write(MySendToMessage respMsg) {
		if (!channel.isActive()) {
			respMsg.release();
			return;
		}
		ByteBuf rawBytes;
		try {
			rawBytes = respMsg.entireMsg();
			BinaryWebSocketFrame retFrame = new BinaryWebSocketFrame(rawBytes);
			getChannel().write(retFrame);
		} catch (IOException e) {
			logger.error("",e);
		}
	}

	public void write(SendToMessageRaw respMsg) {
		if (!channel.isActive()) {
			respMsg.release();
			return;
		}
		logger.info("write,msgCode={}",respMsg.getMsgCode());
		ByteBuf rawBytes = respMsg.entireMsg();
		getChannel().write(rawBytes);
	}
	
	public void writeAll(MySendToMessage respMsg) {
		if (!channel.isActive()) {
			return;
		}
		ByteBuf rawBytes;
		try {
			rawBytes = respMsg.entireMsgAll();
			BinaryWebSocketFrame retFrame = new BinaryWebSocketFrame(rawBytes);
			getChannel().write(retFrame);
		} catch (IOException e) {
			logger.error("",e);
		}
	}

	public boolean isChannelActive() {
		return channel.isActive();
	}

	/**
	 * 在一次请求中，同一个channel写入了多个消息，写入的时候，channel做了缓存
	 * 等到最后一个消息写入channel之后，执行flush方法，将所有消息内容发送给系统的信道，清空channel的缓存
	 */
	public void flush() {
		getChannel().flush();
	}
	
	public void writeAndFlush(SendToMessage respMsg) {
		if (!channel.isActive()) {
			return;
		}
		getChannel().writeAndFlush(respMsg);
	}
	
	public void writeAndFlush(SendToMessageRaw respMsg) {
		if (!channel.isActive()) {
			respMsg.release();
			return;
		}
		logger.info("writeAndFlush,msgCode={}",respMsg.getMsgCode());
		ByteBuf rawBytes = respMsg.entireMsg();
		getChannel().writeAndFlush(rawBytes);
	}

	public void writeAndFlush(MySendToMessage respMsg) {
		if (!channel.isActive()) {
			respMsg.release();
			return;
		}
		try {
			ByteBuf rawBytes = respMsg.entireMsg();
			BinaryWebSocketFrame retFrame = new BinaryWebSocketFrame(rawBytes);
			getChannel().writeAndFlush(retFrame);
		} catch (IOException e) {
			logger.error("",e);
		}
	}
	
	public void writeAndFlushAll(MySendToMessage respMsg) {
		if (!channel.isActive()) {
			return;
		}
		try {
			ByteBuf rawBytes = respMsg.entireMsgAll();
			BinaryWebSocketFrame retFrame = new BinaryWebSocketFrame(rawBytes);
			getChannel().writeAndFlush(retFrame);
		} catch (IOException e) {
			logger.error("",e);
		}
	}

	public void write(int msgCode, RetCode retCode) {
		if (!channel.isActive()) {
			return;
		}
		getChannel().write(new ResponseProtoMessage(msgCode, retCode));
		// logger.info("write,msgCode={},retCode={}", msgCode, retCode);
	}

	public void write(int msgCode, MessageLite.Builder msgBuilder) {
		if (!channel.isActive()) {
			return;
		}
		getChannel().write(new ResponseProtoMessage(msgCode, RetCode.RET_OK, (GeneratedMessageV3) msgBuilder.build()));
		ProcessorStatManager.getInstance().logEnd(msgCode, channel);
		// logger.info("write,msgCode={}", msgCode);
	}

	public void writeAndFlush(int msgCode, RetCode retCode) {
		if (!channel.isActive()) {
			return;
		}
		getChannel().writeAndFlush(new ResponseProtoMessage(msgCode, retCode));
		ProcessorStatManager.getInstance().logEnd(msgCode, channel);
		// logger.info("writeAndFlush,msgCode={},retCode={}", msgCode, retCode);
	}

	public void write(int msgCode, GeneratedMessageV3 respMsg) {
		if (!channel.isActive()) {
			return;
		}
		getChannel().write(new ResponseProtoMessage(msgCode, RetCode.RET_OK, respMsg));
		// logger.info("write,msgCode={}", msgCode);
	}

	public void writeAndFlush(int msgCode, MessageLite.Builder msgBuilder) {
		if (!channel.isActive()) {
			return;
		}
		getChannel().writeAndFlush(
				new ResponseProtoMessage(msgCode, RetCode.RET_OK, (GeneratedMessageV3) msgBuilder.build()));
		ProcessorStatManager.getInstance().logEnd(msgCode, channel);
		// logger.info("writeAndFlush,msgCode={}", msgCode);
	}

	public void writeAndFlush(int msgCode, GeneratedMessageV3 respMsg) {
		if (!channel.isActive()) {
			return;
		}
		getChannel().writeAndFlush(new ResponseProtoMessage(msgCode, RetCode.RET_OK, respMsg));
		ProcessorStatManager.getInstance().logEnd(msgCode, channel);
		// logger.info("writeAndFlush,msgCode={}", msgCode);
	}

	public ChannelFuture close() {
		return getChannel().close();
	}

	public Long getSessionId() {
		return getChannel().attr(Netty4Server.KEY_SESSION_ID).get();
	}

	public void saveSessionId(Long sessionId) {
		getChannel().attr(Netty4Server.KEY_SESSION_ID).set(sessionId);
	}

	public Channel getChannel() {
		return channel;
	}

	public void setChannel(Channel channel) {
		this.channel = channel;
	}

}
